package com.example.day43_opengl_filter2;

import android.content.Context;
import android.opengl.GLES20;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

/**
 * Description:
 * Created by Gdu on 2021/5/7 1:25.
 */

public class AbstractFilter {

    //GPU顶点坐标缓冲区
    FloatBuffer vertexBuffer;
    //纹理坐标
    FloatBuffer textureBuffer;
    //顶点着色器四个点的坐标
    float[] VERTEX = {
            -1.0f,-1.0f,
            1.0f,-1.0f,
            -1.0f,1.0f,
            1.0f,1.0f
    };
    //纹理坐标 surface坐标
    float[] TEXTURE = {
            0.0f,0.0f,
            1.0f,0.0f,
            0.0f,1.0f,
            1.0f,1.0f
    };
    public final int program;
    //句柄 就是GPU中的vPosition
    private int vPosition;
    private int vCoord;
    private int vTexture;
    private int vMatrix;
    private int mHeight;
    private int mWidth;
    private float[] mtx;

    public AbstractFilter(Context context,int vertexShaderId,int fragmentShaderId) {
        //allocateDirect申请的内存是连续的,及时的
        //大小是:4个坐标,一个坐标占4位,每个坐标有x,y两个值
        vertexBuffer = ByteBuffer.allocateDirect(4*4*2).order(ByteOrder.nativeOrder()).asFloatBuffer();
        vertexBuffer.clear();
        vertexBuffer.put(VERTEX);
        //纹理坐标赋值
        textureBuffer = ByteBuffer.allocateDirect(4*4*2).order(ByteOrder.nativeOrder()).asFloatBuffer();
        textureBuffer.clear();
        textureBuffer.put(TEXTURE);

        //把raw中的文件读取出来
        String vertexSharder = OpenGLUtils.readRawTextFile(context,vertexShaderId);
        String fragSharder = OpenGLUtils.readRawTextFile(context,fragmentShaderId);
        //先编译 再链接 再运行
        program = OpenGLUtils.loadProgram(vertexSharder,fragSharder);
        //取出gpu程序中的vPosition地址
        vPosition = GLES20.glGetAttribLocation(program,"vPosition");
        //接收纹理坐标, 采样器采取图片的坐标
        vCoord = GLES20.glGetAttribLocation(program,"vCoord");
        //采样点的坐标
        vTexture = GLES20.glGetUniformLocation(program,"vTexture");
    }

    public void setTransformMatrix(float[] mtx){
        this.mtx = mtx;
    }

    public void setSize(int width,int height){
        mWidth = width;
        mHeight = height;
    }

    /**
     * 获取摄像头的数据
     * @param textures
     */
    public int onDraw(int textures) {
        //传递openGL view的大小
        GLES20.glViewport(0,0,mWidth,mHeight);
        //使用程序
        GLES20.glUseProgram(program);
        //从索引为0的地方读  将数据清零
        vertexBuffer.position(0);
        //将句柄和数据进行绑定
        //index 指定要修改的通用顶点属性的索引
        //size 指定每个通用顶点属性的组件数
        //type 指定数组中每个组件的数据类型
        // normalized 指定在访问顶点数据值时是应将其标准化(GL_TURE)还是直接转换成顶点值
        GLES20.glVertexAttribPointer(vPosition,2,GLES20.GL_FLOAT,false,0,vertexBuffer);
        //开启读写,让上面这一句生效
        GLES20.glEnableVertexAttribArray(vPosition);

        textureBuffer.position(0);
        GLES20.glVertexAttribPointer(vCoord,2,GLES20.GL_FLOAT,false,0,textureBuffer);
        GLES20.glEnableVertexAttribArray(vCoord);
        //激活图层,当前图层是0 就是textures[0]的值
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        //生成一个采样器
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,textures);
        //将采样器赋值
        GLES20.glUniform1i(vTexture,textures);
        beforeDraw();
        //通知渲染 GL_TRIANGLE_STRIP画画模式,first:从哪开始 count:几个坐标
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP,0,4);
        //绑定采样器
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,textures);
        return textures;
    }

    /**
     * 模板方法
     */
    public void beforeDraw(){

    }

    public void release(){
        GLES20.glDeleteProgram(program);
    }

}
